#ifndef __SYSTEM_H__
#define __SYSTEM_H__
#include "CH554.h"

// #define USE_EXTR_CLK

// 定义函数返回值
#ifndef SUCCESS
#define SUCCESS 0
#endif
#ifndef FAIL
#define FAIL 0xFF
#endif

// 定义定时器起始
#ifndef START
#define START 1
#endif
#ifndef STOP
#define STOP 0
#endif

#define TIME_CNT_CAL 

#define SetBit(Param, Bits) Param |= Bits
#define ResetBit(Param, Bits) Param &= ~Bits
#define GetBit(Param, Bits) (Param & Bits)

#ifndef DE_PRINTF
// #define  DE_PRINTF      1
#endif
#define Fosc 16000000                // 系统主频16MHz
#define Fsys 16000000                // 系统主频16MHz
#define T1US_COUNT (Fsys / 1000000)  // 1us计数值
#define T1MS_COUNT (Fsys / 1000)     // 1ms计数值
#define USE_HW_MS_DELAY
// #define USE_HW_TIMER_MS_DELAY

typedef enum {
  sfExt = -1,
  sf187_5KHz = 0x00,
  sf750KHz,
  sf3MHz,
  sf6MHz,
  sf12MHz,
  sf16MHz,
  sf24MHz,
  sf32MHz,
} SysFreqType;

typedef enum {
  tm13bits = 0x00,
  tm16bits,
  tm8bitsAutoload,
  tm8bitsDual,
} TimerMode;

typedef enum {
  t2clkExtT2Pin = -1,
  tnclkFsysDiv12 = 0,
  tnclkFsysDiv4,
  tnclkFsys
} TimerClk;

typedef enum {
  umM0_ShiftRegFsysDiv12 = 0,  // 8位移位寄存器固定波特率
  umM1_8BitsT1T2,
  umM2_9BitsFsysDiv128Div32,
  umM3_9BitsT1T2,
} UartMode;

typedef enum {
  ubcFsysDiv12 = 0,
  ubcFsysDiv32,
  ubcFsysDiv128,
  ubcTimer1,
  ubcTimer2
} UartBaudClk;

#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80

#define IntrLowLevel 0
#define IntrFalling 1

#define safe_enter() SAFE_MOD = 0x55; SAFE_MOD = 0xAA // enter safe mode, write 0x55, 0xAA
#define safe_exit() SAFE_MOD = 0x00 // exit safe mode, write 0x00

#define irq_enable(AIsEnable) EA = AIsEnable

#define intr0_irq_enable(AIsEnable) EX0 = AIsEnable
#define intr0_irq_mode(mode) IT0 = mode

#define intr1_irq_enable(AIsEnable) EX1 = AIsEnable
#define intr1_irq_mode(mode) IT1 = mode

extern xdata uint16_t FTimer0Count;

#define timer0_enable(AIsEnable) TR0 = AIsEnable
#define timer0_irq_enable(AIsEnable) ET0 = AIsEnable
#define timer0_irq_flag (TF0 ? true : false)
#define timer0_irq_clear() TF0 = 0

extern xdata uint16_t FTimer1Count;
#ifdef USE_SDCC
inline void timer1_set_timeout(uint16_t ATimeoutUs) {
  FTimer1Count = ATimeoutUs * Fosc / 1000000;
  TH1 = FTimer1Count >> 8;
  TL1 = FTimer1Count;
  // upward timer. caculate timeout = (1000000 / Ft0clk) * count
}
#else
#define timer1_set_timeout(ATimeoutUs)          \
  do {                                          \
    FTimer1Count = ATimeoutUs * Fosc / 1000000; \
    TH1 = FTimer1Count >> 8;                    \
    TL1 = FTimer1Count;                         \
  } while (0)  // upward timer. caculate timeout = (1000000 / Ft0clk) * count
#endif
#define timer1_enable(AIsEnable) TR1 = AIsEnable
#define timer1_irq_enable(AIsEnable) ET1 = AIsEnable
#define timer1_irq_flag (TF1 ? true : false)
#define timer1_irq_clear TF1 = 0

// Timer2 can use for uart baudrate generation. only autoload mode
#ifdef USE_SDCC
inline void timer2_mode(uint16_t _TimerClk) {
  ResetBit(T2MOD, bT2_CAP1_EN);
  ResetBit(T2MOD, T2OE);
  C_T2 = 0;
  ResetBit(T2MOD, bT2_CLK);
  RCLK = 0;
  TCLK = 0;
  CP_RL2 = 0;
  if (_TimerClk == tnclkFsysDiv4) {
    SetBit(T2MOD, bT2_CLK);
    ResetBit(T2MOD, bTMR_CLK);
  } else if (_TimerClk == tnclkFsys) {
    SetBit(T2MOD, bT2_CLK);
    SetBit(T2MOD, bTMR_CLK);
  } else if (_TimerClk == t2clkExtT2Pin) {
    C_T2 = 1;
  }
  // slow = fsys/12; fast1 = fsys/4; fast2 = fsys
}

inline void timer2_set_timeout(uint16_t ATimeoutUs) {
  T2COUNT = ATimeoutUs * Fosc / 1000000;
  RCAP2H = T2COUNT >> 8;
  RCAP2L = (T2COUNT) & 0xFF;
  // upward timer. caculate timeout = (1000000 / Ft0clk) * count
}
#else
#define timer2_mode(_TimerClk)               \
  do {                                       \
    ResetBit(T2MOD, bT2_CAP1_EN);            \
    ResetBit(T2MOD, T2OE);                   \
    C_T2 = 0;                                \
    ResetBit(T2MOD, bT2_CLK);                \
    RCLK = 0;                                \
    TCLK = 0;                                \
    CP_RL2 = 0;                              \
    if (_TimerClk == tnclkFsysDiv4) {        \
      SetBit(T2MOD, bT2_CLK);                \
      ResetBit(T2MOD, bTMR_CLK);             \
    } else if (_TimerClk == tnclkFsys) {     \
      SetBit(T2MOD, bT2_CLK);                \
      SetBit(T2MOD, bTMR_CLK);               \
    } else if (_TimerClk == t2clkExtT2Pin) { \
      C_T2 = 1;                              \
    }                                        \
  } while (0)  // slow = fsys/12; fast1 = fsys/4; fast2 = fsys

#define timer2_set_timeout(ATimeoutUs)     \
  do {                                     \
    T2COUNT = ATimeoutUs * Fosc / 1000000; \
    RCAP2H = T2COUNT >> 8;                 \
    RCAP2L = (T2COUNT) & 0xFF;             \
  } while (0)  // upward timer. caculate timeout = (1000000 / Ft0clk) * count
#endif
#define timer2_enable(AIsEnable) TR2 = AIsEnable
#define timer2_irq_enable(AIsEnable) ET2 = AIsEnable
#define timer2_irq_flag (TF2 ? true : false)
#define timer2_irq_clear TF2 = 0

#define pwm_set_clk(AFsysDiv) PWM_CK_SE = AFsysDiv
#define pwm_irq_enable(AIsEnable) bPWM_IF_END = AIsEnable
#define pwm1_enable(AIsEnable) bPWM1_OUT_EN = AIsEnable
#define pwm1_polar(AIsHigh) bPWM1_POLAR = AIsHigh
#define pwm1_output(ARange) PWM_DATA1 = ARange
#define pwm2_enable(AIsEnable) bPWM2_OUT_EN = AIsEnable
#define pwm2_polar(AIsHigh) bPWM2_POLAR = AIsHigh
#define pwm2_output(ARange) PWM_DATA2 = ARange

#define uart0_recv_enable(AIsEnable) REN = AIsEnable
#define uart0_irq_enable(AIsEnable) ES = AIsEnable
#define uart0_recv_flag() (RI ? true : false)
#define uart0_recv_clear() RI = 0
#define uart0_send_flag() (TI ? true : false)
#define uart0_send_clear() TI = 0
#define uart0_read_buffer() SBUF
#define uart0_write_buffer(buf) SBUF = buf

/*
 * Function Name  : Uart0SetPinAlter()
 * Description    : CH554串口0引脚映射,串口映射到P0.2和P0.3
 */
#ifdef USE_SDCC
inline void Uart0SetPinAlter(void) { SetBit(PIN_FUNC, bUART0_PIN_X); }
#else
#define Uart0SetPinAlter() \
  SetBit(PIN_FUNC, bUART0_PIN_X)  // 串口映射到P1.2和P1.3
#endif

/* Input: 看门狗复位时间设置
         00H(6MHz)=2.8s
         80H(6MHz)=1.4s
*/
#ifdef USE_SDCC
inline void WdtFeed(uint8_t ATime) {
  WDOG_COUNT = ATime;  // 看门狗计数器赋值
}
#else
#define WdtFeed(ATime) WDOG_COUNT = ATime  // 看门狗计数器赋值
#endif

void DelayUs(uint16_t n); /* 以uS为单位延时 */
void DelayMs(uint16_t n); /* 以mS为单位延时 */

void SystemInit(SysFreqType SysFreq); /* CH554时钟选择和配置 */

uint16_t TimerxTick(TimerClk ATimerClk, uint16_t ATimeoutUs);
void Timer0Init(TimerMode ATimerMode, TimerClk ATimerClk);
void Timer0Reload(uint8_t ATLCnt, uint8_t ATHCnt);

void Timer1Init(TimerMode ATimerMode, TimerClk ATimerClk);
void Timer1Reload(uint8_t ATLCnt, uint8_t ATHCnt);

void Uart0Alter(void); /* CH554串口0引脚映射到P0.2/P0.3 */
uint32_t Uart0Init(UartMode AUartMode, UartBaudClk AUartBaudClk,
               uint32_t AInOutBaudRate);
uint8_t Uart0RcvByte(void); /* CH554 UART0查询方式接收一个字节 */

#ifdef DEBUG_OFF
#define Uart0Printf(str)
#else
void Uart0Printf(const char* str);
#endif

void Uart0SendByte(uint8_t SendDat); /* Uart0发送一个字节 */
void Uart1Init(uint32_t ABuadRate);  /* UART1 配置 */
uint8_t Uart1RcvByte(void); /* CH554 UART1查询方式接收一个字节 */

void Uart1SendByte(uint8_t SendDat); /* Uart1发送一个字节 */
void WdtModeSelect(bool enable);    /* CH554看门狗模式设置 */

#endif
